package org.fly.jingwei.ext;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.fly.jingwei.ext.core.PropsUI;
import org.fly.jingwei.ext.utils.PropUtils;
import org.pentaho.di.core.DBCache;
import org.pentaho.di.core.RowMetaAndData;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.logging.*;
import org.pentaho.di.core.row.RowMeta;
import org.pentaho.di.job.JobExecutionConfiguration;
import org.pentaho.di.repository.LongObjectId;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.repository.kdr.KettleDatabaseRepository;
import org.pentaho.di.repository.kdr.KettleDatabaseRepositoryMeta;
import org.pentaho.di.trans.TransExecutionConfiguration;
import org.pentaho.metastore.stores.delegate.DelegatingMetaStore;

import java.util.ArrayList;

/**
 * @author leo.jie (weixiao.me@aliyun.com)
 * @version 1.0
 * @organization bigdata
 * @website https://www.jielongping.com
 * @date 2020/6/2 11:18 下午
 * @since 1.0
 */
public class SingleApp {
    public static KettleDatabaseRepositoryMeta meta;

    private final LogChannelInterface log;
    private final TransExecutionConfiguration transExecutionConfiguration;
    private final TransExecutionConfiguration transPreviewExecutionConfiguration;
    private final TransExecutionConfiguration transDebugExecutionConfiguration;
    private final JobExecutionConfiguration jobExecutionConfiguration;
    private final PropsUI props;

    private static class AppHolder {
        private static final SingleApp INSTANCE = new SingleApp();
    }

    public static SingleApp getInstance() {
        return AppHolder.INSTANCE;
    }

    private SingleApp() {
        props = PropsUI.getInstance();
        log = new LogChannel(PropsUI.getAppName());
        loadSettings();
        transExecutionConfiguration = new TransExecutionConfiguration();
        transExecutionConfiguration.setGatheringMetrics(true);
        transPreviewExecutionConfiguration = new TransExecutionConfiguration();
        transPreviewExecutionConfiguration.setGatheringMetrics(true);
        transDebugExecutionConfiguration = new TransExecutionConfiguration();
        transDebugExecutionConfiguration.setGatheringMetrics(true);

        jobExecutionConfiguration = new JobExecutionConfiguration();

        variables = new RowMetaAndData(new RowMeta());
    }

    public void loadSettings() {
        LogLevel logLevel = LogLevel.getLogLevelForCode(props.getLogLevel());
        DefaultLogLevel.setLogLevel(logLevel);
        log.setLogLevel(logLevel);
        KettleLogStore.getAppender().setMaxNrLines(props.getMaxNrLinesInLog());
        initKettleDb();
        // transMeta.setMaxUndo(props.getMaxUndo());
        DBCache.getInstance().setActive(props.useDBCache());
    }

    private Repository repository;

    public Repository getRepository() {
        return repository;
    }

    private Repository defaultRepository;

    public Repository getDefaultRepository() {
        return this.defaultRepository;
    }

    public void selectRepository(Repository repo) {
        if (repository != null) {
            repository.disconnect();
        }
        repository = repo;
    }

    private DelegatingMetaStore metaStore;

    public DelegatingMetaStore getMetaStore() {
        return metaStore;
    }

    public LogChannelInterface getLog() {
        return log;
    }

    private RowMetaAndData variables;
    private ArrayList<String> arguments = new ArrayList<>();


    public String[] getArguments() {
        return arguments.toArray(new String[arguments.size()]);
    }

    public JobExecutionConfiguration getJobExecutionConfiguration() {
        return jobExecutionConfiguration;
    }

    public TransExecutionConfiguration getTransDebugExecutionConfiguration() {
        return transDebugExecutionConfiguration;
    }

    public TransExecutionConfiguration getTransPreviewExecutionConfiguration() {
        return transPreviewExecutionConfiguration;
    }

    public TransExecutionConfiguration getTransExecutionConfiguration() {
        return transExecutionConfiguration;
    }

    public RowMetaAndData getVariables() {
        return variables;
    }

    public void initKettleDb() {
        String jdbcType = PropUtils.getKettleJdbcProp().getValue("jdbc.type");
        String hostName = PropUtils.getKettleJdbcProp().getValue("jdbc.hostName");
        String port = PropUtils.getKettleJdbcProp().getValue("jdbc.port");
        String dbName = PropUtils.getKettleJdbcProp().getValue("jdbc.dbName");
        String username = PropUtils.getKettleJdbcProp().getValue("jdbc.username");
        String password = PropUtils.getKettleJdbcProp().getValue("jdbc.password");
        String jdbcParams = PropUtils.getKettleJdbcProp().getValue("jdbc.jdbcParams");

        KettleDatabaseRepository repository = new KettleDatabaseRepository();
        String prefix = hostName + "_" + port + "_" + dbName;

        DatabaseMeta dbMeta = new DatabaseMeta();

        dbMeta.setName(prefix + "_Database");
        dbMeta.setDBName(dbName);
        dbMeta.setDatabaseType(jdbcType);
        dbMeta.setAccessType(0);
        dbMeta.setHostname(hostName);
        dbMeta.setServername(hostName);
        dbMeta.setDBPort(port);
        dbMeta.setUsername(username);
        dbMeta.setPassword(password);
        ObjectId objectId = new LongObjectId(100);
        dbMeta.setObjectId(objectId);
        dbMeta.setShared(true);

        if (StringUtils.isNotBlank(jdbcParams)) {
            String[] jdbcParamArray = jdbcParams.split("&");
            if (jdbcParamArray.length > 0) {
                for (String param : jdbcParamArray) {
                    String[] kv = param.split("=");
                    if (kv.length == 2) {
                        dbMeta.addExtraOption(dbMeta.getPluginId(), kv[0], kv[1]);
                    }
                }
            }
        }

        dbMeta.setUsingConnectionPool(true);

        meta = new KettleDatabaseRepositoryMeta();
        meta.setName(prefix + "_DatabaseRepository");
        meta.setId("KettleDatabaseRepository");
        meta.setConnection(dbMeta);
        meta.setDescription(prefix + "_DatabaseRepository");

        repository.init(meta);
        try {
            repository.connect("admin", "admin");
        } catch (KettleException e) {
            e.printStackTrace();
        }
        this.repository = repository;
    }


}
